package com.wondersgroup.restbase.dto;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.wondersgroup.restbase.util.AccessorUtils;

public class NativeQueryMapInfo {

	private String nativeQueryField;
	private String dtoField;
	private boolean input;
	private boolean output;

	public boolean isOutput() {
		return this.output;
	}

	public void setOutput(boolean output) {
		this.output = output;
	}

	public boolean isInput() {
		return input;
	}

	public void setInput(boolean input) {
		this.input = input;
	}

	public String getDtoField() {
		return dtoField;
	}

	public void setDtoField(String dtoField) {
		this.dtoField = dtoField;
	}

	public String getNativeQueryField() {
		return nativeQueryField;
	}

	public void setNativeQueryField(String nativeQueryField) {
		this.nativeQueryField = nativeQueryField;
	}

	public static <DTO> List<NativeQueryMapInfo> build(Class<DTO> dtoClass) {
		List<NativeQueryMapInfo> mapList = new ArrayList<NativeQueryMapInfo>();
		for (Field field : dtoClass.getDeclaredFields()) {
			NativeQueryMapping fieldMapping = field.getAnnotation(NativeQueryMapping.class);
			if (fieldMapping != null) {
				NativeQueryMapInfo mapInfo = new NativeQueryMapInfo();
				mapInfo.setDtoField(field.getName());
				mapInfo.setInput(fieldMapping.input());
				mapInfo.setOutput(fieldMapping.output());
				if (fieldMapping.nativeQueryField().equals("")) {
					mapInfo.setNativeQueryField(field.getName());
				} else {
					mapInfo.setNativeQueryField(fieldMapping.nativeQueryField());
				}

				mapList.add(mapInfo);
			}
		}
		return mapList;
	}

	@SuppressWarnings("rawtypes")
	public <DTO, MODEL> void setModelField(DTO dto, MODEL model) throws Exception {

		if (!input)
			return;

		Method getter = AccessorUtils.findGetter(dto, getDtoField());
		if (getter.invoke(dto) == null)
			return;

		if (getDtoField().indexOf(".") < 0) {

			Method setter = AccessorUtils.findSetter(model, getDtoField());
			// modify by wym 增加对日期类型的处理
			Class firstParamType = setter.getParameterTypes()[0];
			if (firstParamType == java.util.Date.class) {
				String arg = (String) getter.invoke(dto);
				Date date = null;
				if (arg != null && !arg.equals("")) {
					String formatStr = arg.split(" ").length > 1 ? "yyyy-MM-dd HH:mm:ss" : "yyyy-MM-dd";
					SimpleDateFormat sdf = new SimpleDateFormat(formatStr);
					date = sdf.parse(arg);
				}
				setter.invoke(model, date);
			} else if (firstParamType == java.lang.Integer.class) {
				setter.invoke(model, Integer
						.parseInt((getter.invoke(dto).toString()).equals("") ? "0" : getter.invoke(dto).toString()));
			} else {
				setter.invoke(model, getter.invoke(dto));
			}

		} else {
			String[] fields = getDtoField().split("\\.");

			Object obj = model;
			for (int i = 0; i < fields.length - 1; i++) {
				Method m = AccessorUtils.findGetter(obj, fields[i]);
				Object ret = m.invoke(obj);
				if (ret == null) {
					ret = m.getReturnType().newInstance();
					AccessorUtils.findSetter(obj, fields[i]).invoke(obj, ret);
				}
				obj = ret;
			}

			AccessorUtils.findSetter(obj, fields[fields.length - 1]).invoke(obj, getter.invoke(dto));
		}
	}
}
